package com.baizhi.utils;


import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MyBatisUtils {
	private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<SqlSession>();
	private static SqlSessionFactory sqlSessionFactory=null;
	static{
		Reader resourceAsReader = null;
		try {
			resourceAsReader = Resources.getResourceAsReader("mybatis/mybatis-config.xml");
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("读取配置文件异常");
		}
		sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsReader);
		if(resourceAsReader!=null) {
			try {
				resourceAsReader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	private MyBatisUtils(){
	}

	public static SqlSession getSqlSession(){
		SqlSession sqlSession = threadLocal.get();
		if(sqlSession==null){
			sqlSession = sqlSessionFactory.openSession(false);
			threadLocal.set(sqlSession);
		}
		return sqlSession;
	}

	/**
	 * 产生动态代理的sqlSession对象，修改原来的commit与rollback方法
	 * @return
	 */
	public static SqlSession getProxySqlsession(){
		final SqlSession sqlSession = getSqlSession();
		SqlSession proxySqlSession = (SqlSession) Proxy.newProxyInstance(sqlSession.getClass().getClassLoader(), new Class[]{SqlSession.class}, new InvocationHandler() {
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				if(method.getName().equals("commit")){
					Object invoke = method.invoke(sqlSession, args);
					close(sqlSession);
					return invoke;
				}
				else if(method.getName().equals("rollback")){
					Object invoke = method.invoke(sqlSession, args);
					close(sqlSession);
					return invoke;
				}
				else if(method.getName().equals("close")){
					close(sqlSession);
					return null;
				}
				else{
					return method.invoke(sqlSession,args);
				}
			}
		});
		return proxySqlSession;
	}

	public static void close(SqlSession sqlSession) {
		if(sqlSession!=null) {
			sqlSession.close();
			threadLocal.remove();
			if(threadLocal!=null){
				threadLocal.set(null);
			}
		}
	}
}
